package jrain.fw.dao.common.parser.bean;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jrain.fw.core.consts.Consts;
import jrain.fw.core.dao.bean.SqlBean;
import jrain.fw.dao.common.utils.SqlUtils;
import jrain.utils.collection.CollectionUtils;
import jrain.utils.consts.BaseConst;
import jrain.utils.exception.ServiceException;
import jrain.utils.lang.LangUtils;
import jrain.utils.lang.StringUtils;

public class VarExpression extends SqlExpression {

	private String var;

	public String getVar() {
		return var;
	}

	public void setVar(String var) {
		this.var = var;
	}

	public String calcSql() {
		return var;
	}

	public String calcExpression() {
		return var;
	}

	@Override
	public SqlBean calcSql(Map<String, Object> sqlCfg, Map<String, Object> paramData, Map<String, Object> ctx) {
		SqlBean bean = new SqlBean();
		if (var.equals(Consts.SQL_COLUMNS)) {
			columns(sqlCfg, paramData, bean);
		} else if (var.equals(Consts.SQL_ORDER)) {
			order(sqlCfg, paramData, bean);
		} else if (var.startsWith(Consts.SQL_CONDITION)) {
			// 动态查询条件
			boolean b = condition(sqlCfg, paramData, var, bean.getSql(), bean.getParams(), 1);
			if (b) {
				countCondition(ctx);
			}
		} else if (var.startsWith(Consts.SQL_AND_CONDITION)) {
			// 动态查询条件
			boolean b = condition(sqlCfg, paramData, var, bean.getSql(), bean.getParams(), 1);
			if (b) {
				countCondition(ctx);
			}
		} else if (var.startsWith(Consts.SQL_OR_CONDITION)) {
			// 动态查询条件
			boolean b = condition(sqlCfg, paramData, var, bean.getSql(), bean.getParams(), 2);
			if (b) {
				countCondition(ctx);
			}
		} else if (var.contains(BaseConst.EQ)) {
			String newName = StringUtils.trimNull(var);
			String columnCode = BaseConst.EMPTY;
			String op = BaseConst.EMPTY;
			Object value = null;
			if (newName.startsWith(BaseConst.EQ)) {
				newName = newName.substring(1);
			} else {
				List<String> fieldColumns = CollectionUtils.valueOfList(var, BaseConst.EQ);
				if (fieldColumns.size() == 2) {
					columnCode = fieldColumns.get(0);
					newName = fieldColumns.get(1);
				} else {
					throw new ServiceException("SQL parsing failed, unable to identify" + var);
				}
			}
			if (newName.contains(BaseConst.XHX)) {
				List<String> fields = CollectionUtils.valueOfList(newName, BaseConst.XHX);
				if (fields.size() == 2) {
					op = fields.get(1);
					String fieldName = fields.get(0);
					if (StringUtils.isEmpty(columnCode)) {
						columnCode = SqlUtils.fieldToColumn(fieldName);
					}
					value = paramData.get(fieldName);
				} else {
					throw new ServiceException("SQL parsing failed, unable to identify" + var);
				}
			} else {
				op = Consts.SQL_CONDITION_OP_DVALUE;
				if (StringUtils.isEmpty(columnCode)) {
					columnCode = SqlUtils.fieldToColumn(newName);
				}
				value = paramData.get(newName);
			}
			// 字段转换
			SqlUtils.parseQueryCondition(columnCode, op, value, bean.getSql(), bean.getParams(), 3);
			countVar(ctx);
		} else if (var.contains(BaseConst.XHX)) {
			// 值转换
			List<String> fields = CollectionUtils.valueOfList(var, BaseConst.XHX);
			if (fields.size() == 2) {
				bean.getSql().append(BaseConst.CQUESTION);
				String fieldName = fields.get(0);
				String columnCode = SqlUtils.fieldToColumn(fieldName);
				String op = fields.get(1);
				Object value = paramData.get(fieldName);
				SqlUtils.parseQueryCondition(columnCode, op, value, new StringBuilder(), bean.getParams(), 3);
				countVar(ctx);
			} else {
				throw new ServiceException("SQL parsing failed, unable to identify" + var);
			}

		} else {
			// 值替换
			Object value = paramData.get(var);
			bean.getSql().append(BaseConst.CQUESTION);
			bean.addParam(value);
			countVar(ctx);
		}
		return bean;
	}

	protected void columns(Map<String, Object> sqlCfg, Map<String, Object> paramData, SqlBean calcBean) {
		String sqlType = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_TYPE));
		if (Consts.CFG_SQL_TYPE_UPDATE.equals(sqlType)) {
			StringBuilder setSb = new StringBuilder();
			List<String> columns = CollectionUtils.valueOfList(StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_COLUMNS)));
			for (String column : columns) {
				List<String> fields = CollectionUtils.valueOfList(column, BaseConst.EMPTY_SPACE);
				String columnCode = column;
				String fieldCode = SqlUtils.columnToField(columnCode);
				if (fields.size() == 2) {
					columnCode = fields.get(0);
					fieldCode = fields.get(1);
				}
				// 根据用户是否输入列，判定是否更新
				boolean b = paramData.keySet().contains(fieldCode);
				if (b) {
					setSb.append(columnCode);
					setSb.append(" = ?,");
					calcBean.addParam(paramData.get(fieldCode));
				}
			}
			if (setSb.length() > 0) {
				setSb.deleteCharAt(setSb.lastIndexOf(BaseConst.COMMA));
			}
			calcBean.append(setSb.toString());
		} else {
			String columnsStr = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_COLUMNS));
			List<String> showList = CollectionUtils.valueOfList((String) paramData.get(Consts.SQL_SHOW_COLUMNS));
			List<String> ignoreList = CollectionUtils.valueOfList((String) paramData.get(Consts.SQL_IGNORE_COLUMNS));
			StringBuilder columnSb = new StringBuilder();
			if (showList.size() > 0 || ignoreList.size() > 0) {
				List<String> tempColumns = CollectionUtils.valueOfList(columnsStr);
				List<String> fieldCodes = new ArrayList<String>();
				// 列转字段
				for (String tcolumns : tempColumns) {
					if (tcolumns.contains(BaseConst.POINT)) {
						List<String> tempList = CollectionUtils.valueOfList(tcolumns);
						if (tempList.size() == 2) {
							String pre = tempList.get(0);
							String fieldCode = SqlUtils.columnToField(tempList.get(1));
							fieldCodes.add(pre + BaseConst.POINT + fieldCode);
						}
					} else {
						String fieldCode = SqlUtils.columnToField(tcolumns);
						fieldCodes.add(fieldCode);
					}
				}
				if (showList.size() > 0) {
					for (String showField : showList) {
						// 模糊匹配
						if (showField.contains(BaseConst.MULTI)) {
							String npre = showField.replace(BaseConst.MULTI, BaseConst.EMPTY);
							if (npre.length() > 1 && npre.endsWith(BaseConst.POINT)) {
								for (String tempColumn : fieldCodes) {
									if (tempColumn.startsWith(npre)) {
										// 包含前缀
										if (tempColumn.contains(BaseConst.POINT)) {
											List<String> tempList = CollectionUtils.valueOfList(tempColumn);
											if (tempList.size() == 2) {
												String pre = tempList.get(0);
												String columnCode = SqlUtils.fieldToColumn(tempList.get(1));
												columnSb.append(pre + BaseConst.POINT + columnCode);
											}
										} else {
											String columnCode = SqlUtils.fieldToColumn(tempColumn);
											fieldCodes.add(columnCode);
										}
									}
								}
							}
						} else {
							if (fieldCodes.contains(showField)) {
								columnSb.append(SqlUtils.fieldToColumn(showField));
								columnSb.append(BaseConst.COMMA);
							}
						}
					}
					if (columnSb.length() > 0) {
						columnSb.deleteCharAt(columnSb.lastIndexOf(BaseConst.COMMA));
					}
				} else if (ignoreList.size() > 0) {
					// 删除忽略
					for (String ignoreColumn : ignoreList) {
						if (ignoreColumn.contains(BaseConst.MULTI)) {
							String npre = ignoreColumn.replace(BaseConst.MULTI, BaseConst.EMPTY);
							if (npre.length() > 1 && npre.endsWith(BaseConst.POINT)) {
								for (Iterator<String> iterator = fieldCodes.iterator(); iterator.hasNext();) {
									String tempColumn = (String) iterator.next();
									if (tempColumn.startsWith(npre)) {
										iterator.remove();
									}
								}
							} else {
								fieldCodes.remove(ignoreColumn);
							}
						}
					}
					for (String showField : fieldCodes) {
						columnSb.append(SqlUtils.fieldToColumn(showField));
						columnSb.append(BaseConst.COMMA);
					}
					if (columnSb.length() > 0) {
						columnSb.deleteCharAt(columnSb.lastIndexOf(BaseConst.COMMA));
					}
				}
			}
			if (columnsStr.length() == 0) {
				columnsStr = BaseConst.MULTI;
			}
			if (columnSb.length() > 0) {
				calcBean.append(columnSb.toString());
			} else {
				calcBean.append(columnsStr);
			}
		}

	}

	protected boolean condition(Map<String, Object> sqlCfg, Map<String, Object> paramData, String condition, StringBuilder conditionSql,
			List<Object> conditionData, final int andOr) {
		String conditionColumns = StringUtils.trimNull(sqlCfg.get(condition));
		if (conditionColumns.length() == 0) {
			conditionColumns = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_CONDITION));
		}
		List<String> conditionColumnList = CollectionUtils.valueOfList(conditionColumns);
		condition = condition.replace(Consts.SQL_AND_CONDITION, BaseConst.EMPTY);
		condition = condition.replace(Consts.SQL_OR_CONDITION, BaseConst.EMPTY);
		condition = condition.replace(Consts.SQL_CONDITION, BaseConst.EMPTY);

		final String fgroup = StringUtils.trimNull(condition, Consts.SQL_CONDITION_GROUP_DVALUE);
		if (andOr == 2) {
			conditionSql.append(" and (1=0 ");
		}
		boolean badata = false;
		// 字段处理
		Set<String> keySet = paramData.keySet();
		for (String key : keySet) {
			// c_字段名_条件类型_前缀_分组
			if (key.startsWith(Consts.SQL_CONDITION_PRE)) {
				Object value = paramData.get(key);
				String newKey = key.substring(2);
				String[] keyArray = newKey.split(BaseConst.XHX);
				if (keyArray.length == 2 || keyArray.length == 3 || keyArray.length == 4) {
					// 前缀
					String columnCode = BaseConst.EMPTY;
					if (keyArray.length >= 3) {
						columnCode = keyArray[2];
					}
					if (!StringUtils.isEmpty(columnCode)) {
						columnCode = columnCode + BaseConst.POINT;
					}
					// 字段名称
					columnCode = columnCode + SqlUtils.fieldToColumn(keyArray[0]);
					columnCode = columnCode.toLowerCase();
					// 条件类型
					String op = keyArray[1];
					// 分组
					String paramGroup = Consts.SQL_CONDITION_GROUP_DVALUE;
					if (keyArray.length >= 4) {
						paramGroup = StringUtils.trimNull(keyArray[3], paramGroup);
					}
					// 相同分组并且列在分组中
					if (fgroup.equals(paramGroup) && conditionColumnList.contains(columnCode)) {
						badata = true;
						SqlUtils.parseQueryCondition(columnCode, op, value, conditionSql, conditionData, andOr);
					}
				}
			}
		}
		if (andOr == 2) {
			if (!badata) {
				conditionSql.append(" or 1=1");
			}
			conditionSql.append(BaseConst.RIGHT_XKH);
		}
		return badata;
	}

	protected void order(Map<String, Object> sqlCfg, Map<String, Object> paramData, SqlBean calcBean) {
		List<String> orderList = CollectionUtils.valueOfList(StringUtils.trimNull(paramData.get(Consts.SQL_ORDER)));
		if (orderList.size() > 0) {
			String columnsStr = StringUtils.trimNull(sqlCfg.get(Consts.CFG_SQL_COLUMNS));
			List<String> tempColumns = CollectionUtils.valueOfList(columnsStr);
			List<String> fieldCodes = new ArrayList<String>();
			// 列转字段
			for (String tcolumns : tempColumns) {
				if (tcolumns.contains(BaseConst.POINT)) {
					List<String> tempList = CollectionUtils.valueOfList(tcolumns);
					if (tempList.size() == 2) {
						String pre = tempList.get(0);
						String fieldCode = SqlUtils.columnToField(tempList.get(1));
						fieldCodes.add(pre + BaseConst.POINT + fieldCode);
					}
				} else {
					String fieldCode = SqlUtils.columnToField(tcolumns);
					fieldCodes.add(fieldCode);
				}
			}
			StringBuilder sb = new StringBuilder();
			for (String torder : orderList) {
				List<String> orderOneList = CollectionUtils.valueOfList(torder, BaseConst.EMPTY_SPACE);

				if (orderOneList.size() == 1 || orderOneList.size() == 2) {
					String orderOne = orderOneList.get(0);
					String adsc = "asc";
					if (orderOneList.size() == 2) {
						String tadsc = orderOneList.get(1).toLowerCase();
						if ((tadsc.equals("asc") || tadsc.equals("desc"))) {
							adsc = tadsc;
						}
					}
					if (fieldCodes.contains(orderOne)) {
						if (orderOne.contains(BaseConst.POINT)) {
							List<String> tempList = CollectionUtils.valueOfList(orderOne);
							if (tempList.size() == 2) {
								String pre = tempList.get(0);
								String columnCode = SqlUtils.fieldToColumn(tempList.get(1));
								sb.append(pre);
								sb.append(BaseConst.POINT);
								sb.append(columnCode);
								sb.append(BaseConst.EMPTY_SPACE);
								sb.append(adsc);
								sb.append(BaseConst.COMMA);
							}
						} else {
							String columnCode = SqlUtils.fieldToColumn(orderOne);
							sb.append(columnCode);
							sb.append(BaseConst.EMPTY_SPACE);
							sb.append(adsc);
							sb.append(BaseConst.COMMA);
						}
					}
				}
			}
			if (sb.length() > 0) {
				sb.deleteCharAt(sb.lastIndexOf(BaseConst.COMMA));
				calcBean.append(" order by ");
				calcBean.append(sb.toString());
			}
		}
		// 排序

	}

	public void countCondition(Map<String, Object> ctx) {
		int c = LangUtils.parseInt(ctx.get(Consts.SQL_CTX_COUNT_CONDITION));
		ctx.put(Consts.SQL_CTX_COUNT_CONDITION, c + 1);
	}

	public void countVar(Map<String, Object> ctx) {
		int c = LangUtils.parseInt(ctx.get(Consts.SQL_CTX_COUNT_VAR));
		ctx.put(Consts.SQL_CTX_COUNT_VAR, c + 1);
	}
}
